{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  GNU GCC and Make\n",
    "\n",
    "**The working folder of demo GCC projects is the `./demo`**\n",
    "\n",
    "![](./img/demogccfolder.jpg)\n",
    "\n",
    "\n",
    "\n",
    "In this and following noetebooks,\n",
    "\n",
    "we move to the folder of **`./demo`** from the current folders of Jupyter notebook **`/notebook.`**\n",
    "\n",
    "magic command \n",
    "\n",
    "* `%cd` : Change the current working directory.\n",
    "\n",
    "* `%pwd`: Return the absolute path of current working directory "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "J:\\SEU\\SEE\\PySEE\\home\\notebook\\demo\n"
     ]
    }
   ],
   "source": [
    "%cd ./demo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'J:\\\\SEU\\\\SEE\\\\PySEE\\\\home\\\\notebook\\\\demo'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1The Brief Introduction to GCC\n",
    "\n",
    "### Background: GNU and Free Software\n",
    "\n",
    "The original GNU C Compiler (GCC) is developed by **Richard Stallman(理查德·斯托曼)**, the founder of the `GNU Project`. \n",
    "\n",
    "* [The GNU Project](https://www.gnu.org/) \n",
    "\n",
    "GNU is a Unit-like operating system that is \n",
    "\n",
    ">The name **GNU** is a recursive acronym for “GNU's Not Unix.” “GNU” is pronounced *g'noo*, as one syllable, like saying “grew” but replacing the r with n.\n",
    "\n",
    "* **free software**—that is, it **respects** users' **freedom**.\n",
    "\n",
    "The development of GNU, started in January 1984, is known as the **GNU Project**.\n",
    "\n",
    "**The GNU Project** aim is to give computer users **freedom** and control in their use of their computers and computing devices, by collaboratively developing and providing software that is based on the following freedom rights: \n",
    "\n",
    "* users are free to run the software, share it (copy, distribute), study it and modify it.\n",
    "\n",
    "GNU software guarantees these freedom-rights legally (via its license), and is therefore free software; the use of the word **free** always being taken to refer to **freedom**. Thus. `free software` is a matter of liberty, `not price`.\n",
    "\n",
    "The development of GNU made it possible to **use a computer without software that would trample your freedom.** \n",
    "\n",
    "Many of the programs in GNU are released under the auspices of the GNU Project.\n",
    " \n",
    "**The Free Software Foundation** : https://www.fsf.org/\n",
    "   \n",
    "* The Free Software Foundation (FSF) is a nonprofit with a worldwide mission to promote computer user `freedom`. We defend the rights of all software users.\n",
    "\n",
    "### Free Software and Education\n",
    "\n",
    "https://www.gnu.org/education/education.html\n",
    "\n",
    "**How Does Free Software Relate to Education?**\n",
    "\n",
    "\n",
    "Software freedom plays a **fundamental role** in education. \n",
    "\n",
    "Educational institutions of all levels **should use and teach Free Software** because \n",
    "\n",
    "It is the only software that allows them to **accomplish their essential missions**: \n",
    "\n",
    "* to disseminate human `knowledge` and to prepare students to be good members of their `community`. \n",
    "\n",
    "The **source code and the methods** of Free Software are part of human knowledge.\n",
    "\n",
    "On the contrary, **proprietary software** is `secret, restricted knowledge`, which is the opposite of the mission of educational institutions.\n",
    "\n",
    "Free Software supports education, `proprietary software forbids education.`\n",
    "\n",
    "Free Software is not just a technical question; it is an **ethical, social, and political question**.\n",
    "\n",
    "It is a question of the **human rights** that the **users of software ought to have**.\n",
    "\n",
    "**Freedom** and **cooperation** are **essential values** of Free Software.\n",
    "\n",
    "The GNU System implements these values and the principle of **sharing**, \n",
    "\n",
    "since **sharing** is good and beneficial to **human progress**.\n",
    "\n",
    "\n",
    "### 1.1  Installing GCC\n",
    "\n",
    "**GCC: GNU Compiler Collection** :  http://gcc.gnu.org/\n",
    "  \n",
    "GCC, formerly for \"GNU C Compiler\", has grown over times to support many languages such as `C++`, Objective-C, Java, `Fortran` and Ada. It is now referred to as **\"GNU Compiler Collection\"**. \n",
    " \n",
    "GCC is portable and run in many operating platforms. GCC (and GNU Toolchain) is currently available on all Unixes. They are also ported to **Windows** by `MinGW` and Cygwin. \n",
    "\n",
    "\n",
    "#### Linux\n",
    "\n",
    "GCC (GNU Toolchain) is included in all Linux(Unixes). \n",
    "\n",
    "#### Windows \n",
    "\n",
    "**TDM-GCC**\n",
    "\n",
    "\n",
    "TDM-GCC is a compiler suite for Windows.\n",
    "\n",
    "It combines the most recent stable release of the GCC compiler, a few patches for Windows-friendliness, and the free and open-source `MinGW.org` or `MinGW-w64` runtime APIs, to create a more lightweight open-source alternative to Microsoft’s compiler and platform SDK.\n",
    "\n",
    "https://jmeubank.github.io/tdm-gcc/\n",
    "\n",
    "* https://github.com/jmeubank\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2  Getting Started\n",
    "\n",
    "The GNU C and C++ compiler are gcc and g++, respectively.\n",
    "\n",
    "* **gcc** to compile `C` program\n",
    "\n",
    "* **g++** to compile `C++` program \n",
    "\n",
    "**The Simple Demo: Compile/Link a Simple C Program - hello.c**\n",
    "\n",
    "#### 1.2.1 Make the folders for the GCC projects\n",
    "\n",
    "Generaly,We should put all files of `one project under one folder.`\n",
    "\n",
    "and use the folder of project as **current working folder**\n",
    "\n",
    "In the folder,we should setup `the meaningful folders` to management of `different types` of documents conveniently.\n",
    "\n",
    "We set the folder **./demo/** for the **C/C++ programming** .\n",
    "\n",
    "In the `./demo/`,we set the sub-folder of `src`,`obj` and `bin` for the different type files\n",
    "\n",
    "* ./src: the source code  \n",
    "\n",
    "* ./include: the header file\n",
    "\n",
    "* ./obj: the compiled output object code/\n",
    "\n",
    "* ./bin: the linked output \n",
    "\n",
    "```bash\n",
    " ├──<notebook>\n",
    " │   │ \n",
    " │   │── <demo>\n",
    "           │ \n",
    "           │──<src> \n",
    "           │     │ \n",
    "           │     │─ *.c/cpp (the Source code)\n",
    "           │ \n",
    "           │──<include> \n",
    "           │     │ \n",
    "           │     │─ *.h (the header )\n",
    "           │\n",
    "           │──<obj>\n",
    "           │     │           \n",
    "           │     │─ *.obj/o (the compiled output) \n",
    "           │      \n",
    "           │──<bin>\n",
    "                 │ \n",
    "                 │─ *.exe (the linked output) \n",
    "                           \n",
    "``` \n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.2.2  Compile/Link a Simple C Program\n",
    "\n",
    "We save the code to  the location of source code\n",
    "\n",
    "* source code `hello.c` in `./src` \n",
    "\n",
    "Below is the Hello-world C program `hello.c`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./src/hello.c\n"
     ]
    }
   ],
   "source": [
    "%%file ./src/hello.c\n",
    "/*\n",
    "gcc -o hello hello.c\n",
    "*/\n",
    "#include <stdio.h>\n",
    " \n",
    "int main() {\n",
    "    printf(\"C says Hello, world!\\n\");\n",
    "    return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You need to use **gcc** to `compile` C program：`hello.c`,then `link` to build the output\n",
    "\n",
    "* **-c: source files** `compiles` source files without linking.\n",
    "* **-o: output file** writes the link to build output to the specifies output file name.\n",
    "\n",
    "Use `-o` to set `the specifie output file` to the location`\n",
    "\n",
    "* the Compiled output `hello.o in ./obj/`\n",
    "\n",
    "* the Linked output `hello.exe in the ./bin/`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -c -o ./obj/hello.o ./src/hello.c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have put `hello.o`  in  `.\\obj\\` folder.`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o ./bin/hello ./obj/hello.o"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have put `hello.exe` in the `\\bin\\` folder.`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Compile and Link to build output  at the command**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o ./bin/hello ./src/hello.c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#####  Running Under Windows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!.\\bin\\hello"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####  1.2.3 Compile/Link a Simple C++ Program \n",
    "    \n",
    "- hello.cpp\n",
    "\n",
    "##### Compile/Link the C++ Program : g++\n",
    "\n",
    "Below is the Hello-world C++ program hello.cpp:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./src/hello.cpp\n"
     ]
    }
   ],
   "source": [
    "%%file ./src/hello.cpp\n",
    "/*\n",
    "g++ -o hello hello.cpp\n",
    "*/\n",
    "#include <iostream>\n",
    "using namespace std;\n",
    " \n",
    "int main() {\n",
    "   cout << \"C++ Hello, world!\" << endl;\n",
    "   return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "use **g++** to compile and link C++ program at one command, as follows "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!g++ -o ./bin/hello ./src/hello.cpp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#####  Running Under Windows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!.\\bin\\hello"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.  GNU Make\n",
    "\n",
    "https://www.gnu.org/software/make/\n",
    "\n",
    "The **\"make\"** utility automates the mundane aspects of building executable from source code.\n",
    "\n",
    "**\"make\"** uses a so-called **makefile**, which contains **rules** on how to build the executables.\n",
    "\n",
    "You can issue \"make --help\" to list the command-line options.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!make --help"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1  Create `makefile` file\n",
    "\n",
    "Create the following file named **\"makefile\"** : contains rules and save in the `current` directory. \n",
    "\n",
    "* **`without` any file `extension`**\n",
    "\n",
    "A makefile consists of `a set of rules`（规则） to build the executable. \n",
    "\n",
    "#### 2.1.1  The  rule\n",
    "\n",
    "**A rule** consists of 3 parts:\n",
    "\n",
    "* **a target**（目标）, \n",
    "\n",
    "* **a list of pre-requisites**（条件） \n",
    "\n",
    "* **a command**（命令）\n",
    "\n",
    "as follows:\n",
    "\n",
    "```bash\n",
    "\n",
    "target: pre-req-1 pre-req-2 ...\n",
    "\t  command\n",
    "\n",
    "```\n",
    "\n",
    "* The **target** and **pre-requisites** are separated by <font color=\"red\">a colon ** : **  </font>.\n",
    "\n",
    "\n",
    "* The **command** must be preceded by <font color=\"blue\">**a Tab** (NOT spaces)</font>.\n",
    "\n",
    "```bash\n",
    "target: pre-req-1 pre-req-2 ...\n",
    "<Tab>command\n",
    "```\n",
    "The `target` is the file or thing that `must be made`. The `prerequisites or dependents` are those files that must exist before the target can be successfully created. And the `commands` are those shell commands that will create the target from the prerequisites. \n",
    "\n",
    "The `first rule` seen by make is used as the `default` rule.\n",
    "\n",
    "* The standard first target in many makefiles is called **all**.\n",
    "\n",
    "#### 2.1.2 Comments \n",
    "\n",
    "**`#`** in a line of a makefile starts a comment. \n",
    "\n",
    "It and the rest of the line are ignored, except that `a trailing backslash`(`\\`) not escaped by another backslash will continue the comment across multiple lines. \n",
    "\n",
    "#### 2.1.3  Makeflie for building hello\n",
    "Let's begin to build the same Hello-world program (`hello.c`) into executable (hello.exe) via make utility."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./makefile\n"
     ]
    }
   ],
   "source": [
    "%%file ./makefile\n",
    "# makefile for the hello\n",
    "all: helloexe\n",
    "    \n",
    "helloexe: helloobj\n",
    "\t gcc -o ./bin/hello ./obj/hello.o\n",
    "    \n",
    "helloobj: ./src/hello.c\n",
    "\t gcc -c -o ./obj/hello.o ./src/hello.c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is a rule for compiling a C file, `./src/hello.c` into an object file, `./obj/hello.o`\n",
    "```bash\n",
    "helloobj: ./src/hello.c\n",
    "\t gcc -c -o ./obj/hello.o ./src/hello.c\n",
    "```\n",
    "\n",
    "* 1 The `target` helloobj  appears before the colon(<font color=\"blue\">:</font> ) \n",
    "\n",
    "* 2 The `prerequisites` `./src/hello.c` appear after the colon(<font color=\"blue\">:</font>) \n",
    "\n",
    "* 3 The `command script` appears on the following lines and is preceded by a <font color=\"blue\">tab</font> character.\n",
    "\n",
    "\t <font color=\"blue\">tab</font> gcc -c -o ./obj/hello.o ./src/hello.c\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**NOTE** \n",
    "\n",
    "* [VS Code中makefile报错分隔符](\n",
    "https://gitee.com/thermalogic/home/blob/B2021/guide/doc/Problem_Solution.md#vs-code%E4%B8%ADmakefile%E6%8A%A5%E9%94%99%E5%88%86%E9%9A%94%E7%AC%A6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 Invoking Make  \n",
    "\n",
    "When make is invoked, it automatically creates the **first** `target`  it sees in makefile\n",
    "\n",
    "#### 2.2.1  make  without argument\n",
    "\n",
    "The default nakefile name is: **makefile**, `Makefile`, or `GNUMakefile`. \n",
    "\n",
    "The `makefile` resides in the **same** user’s `current` directory when executing the `make` command.\n",
    "  \n",
    "When make is invoked under these conditions, it automatically creates the `default` first target  `all` it sees. \n",
    "\n",
    "**invoking make in the terminal of `/demo/` without argument** \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -c -o ./obj/hello.o ./src/hello.c\n",
      "gcc -o ./bin/hello ./obj/hello.o\n"
     ]
    }
   ],
   "source": [
    "!make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C says Hello, world!\n"
     ]
    }
   ],
   "source": [
    "!.\\bin\\hello"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2.3 Running make with  target argument \n",
    "\n",
    "We start the target **helloobj** in the makefile\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -c -o ./obj/hello.o ./src/hello.c\n"
     ]
    }
   ],
   "source": [
    "!make helloobj "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2.4 Compile, Link , `Run` and `clean` \n",
    "\n",
    "**Add `clean` target**\n",
    "```bash\n",
    "clean:\n",
    "\t del .\\obj\\hello.o \n",
    "```    \n",
    "\n",
    "**The target `all`**\n",
    "\n",
    "* Add prerequisites `clean`\n",
    "\n",
    "* Add `running command` \n",
    "\n",
    "```bash\n",
    "all: helloexe clean\n",
    "\t ./bin/hello\n",
    "```    \n",
    "then save the  makefile as `./makerun.mk`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing ./makerun.mk\n"
     ]
    }
   ],
   "source": [
    "%%file ./makerun.mk\n",
    "\n",
    "all: helloexe clean\n",
    "\t./bin/hello\n",
    "    \n",
    "helloexe: helloobj\n",
    "\t gcc -o ./bin/hello ./obj/hello.o\n",
    "    \n",
    "helloobj: ./src/hello.c\n",
    "\t gcc -c -o ./obj/hello.o ./src/hello.c\n",
    "\n",
    "clean:\n",
    "\t del .\\obj\\hello.o    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2.5  Invoking make with  the specified FILE as a makefile\n",
    "\n",
    "* `-f FILE`:  Read FILE as a makefile.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -c -o ./obj/hello.o ./src/hello.c\n",
      "gcc -o ./bin/hello ./obj/hello.o\n",
      "del .\\obj\\hello.o    \n",
      "./bin/hello\n",
      "C says Hello, world!\n"
     ]
    }
   ],
   "source": [
    "!make -f makerun.mk"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Compile, Link : Multiple Source Files\n",
    "\n",
    "\n",
    "\n",
    "* 1) The codes of Computing the **mean** of an array\n",
    "\n",
    "  *  statistics.h\n",
    "  *  statistics.c\n",
    "    \n",
    "* 2) The code file of the caller  \n",
    "\n",
    "  *  statdemo.c\n",
    "  \n",
    "**Reference**  GNU:GSL\n",
    "\n",
    "* https://github.com/CNMAT/gsl/blob/master/statistics/mean_source.c  \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./include/statistics.h\n"
     ]
    }
   ],
   "source": [
    "%%file ./include/statistics.h\n",
    "\n",
    "#ifndef STATISTICS_H\n",
    "#define STATISTICS_H\n",
    "\n",
    "double  mean(double data[], int size);\n",
    "\n",
    "//double  mean(double *data, int size);\n",
    "\n",
    "\n",
    "#endif"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./src/statistics.c\n"
     ]
    }
   ],
   "source": [
    "%%file ./src/statistics.c\n",
    "\n",
    "#include \"statistics.h\"\n",
    "\n",
    "//double  mean(double *data, int size)\n",
    "double  mean(double data[], int size)\n",
    "{\n",
    "  /* \n",
    "    Compute the arithmetic mean of a dataset using the recurrence relation \n",
    "       mean_(n) = mean(n-1) + (data[n] - mean(n-1))/(n+1)\n",
    "  */\n",
    "  double mean = 0;\n",
    "  for(int  i = 0; i < size; i++)\n",
    "  {\n",
    "      mean += (data[i] - mean) / (i + 1);\n",
    "   }\n",
    "  return mean;\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./src/statdemo.c\n"
     ]
    }
   ],
   "source": [
    "%%file ./src/statdemo.c\n",
    "\n",
    "#include <stdio.h> \n",
    "#include \"statistics.h\"\n",
    "\n",
    "int main() {\n",
    "     double a[] = {8, 4, 5, 3, 2};\n",
    "     int length = sizeof(a)/sizeof(double);  \n",
    "     printf(\"mean is %f\\n\", mean(a,length)); \n",
    "     return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3 Preprocessor Directives & Once-Only Headers\n",
    "\n",
    "##### Preprocessor Directives\n",
    "\n",
    "http://www.cplusplus.com/doc/tutorial/preprocessor/\n",
    "\n",
    "Preprocessor directives(预处理指令) are lines included in the code of programs preceded by a hash sign (**#**). \n",
    "\n",
    "These lines are not program statements but directives for the preprocessor. The preprocessor examines the code **before actual compilation** of code begins and resolves all these directives before any code is actually generated by regular statements.\n",
    "\n",
    "##### Once-Only Headers\n",
    "\n",
    "Because header files sometimes include one another, it can easily happen that the same file is included **more than once.**\n",
    "\n",
    "For example, suppose the file `statistics.h` contains the line:\n",
    "```c\n",
    "#include <stdio.h>\n",
    "```\n",
    "Then the source file `statdemo.c` that contains the following `#include` directives would include the file `stdio.h` twice, once directly and once indirectly:\n",
    "```c\n",
    "#include <stdio.h>\n",
    "#include \"statistics.h`\n",
    "```\n",
    "\n",
    "If a header file happens to be included **twice**, the compiler will process its contents twice. \n",
    "\n",
    "* This is very likely to cause an error, e.g. when the compiler sees the same structure definition twice. \n",
    "\n",
    "* Even if it does not, it will certainly waste time.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "you can easily guard the contents of a header file against **multiple inclusions**\n",
    "using the directives for `conditional compiling `\n",
    "\n",
    "The standard way to prevent this is to enclose the entire real contents of the file in a conditional, like this:\n",
    "\n",
    "```c\n",
    "#ifndef STATISTICS_H\n",
    "#define STATISTICS_H\n",
    "\n",
    "/* ... The actual contents of the header file statistics.h are here… */\n",
    "\n",
    "#endif /* !STATISTICS_H */\n",
    "```\n",
    "This construct is commonly known as a wrapper **#ifndef**. \n",
    "\n",
    "At the first occurrence of a directive to include the file `SumArray.h`, the macro `SUMARRAY_H` is\n",
    "not yet defined. The preprocessor therefore inserts the contents of the block between\n",
    "`#ifndef and #endif` — including the definition of the macro `SUMARRAY_H`.\n",
    "\n",
    "When the header is included again, the `#ifndef` condition is false, because **SUMARRAY_H** is defined. The preprocessor will skip over the entire contents of the file, and the compiler will not see it twice.\n",
    "\n",
    "> **All header files should have `#ifndef`  and `#endif` guards  to prevent multiple inclusion**\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Compile,Link and Run\n",
    "\n",
    "We usually compile each of the source files **separately** into object file, and link them together in the later stage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -c -o ./obj/statdemo.o ./src/statdemo.c -I./include/\n",
    "!gcc -c -o ./obj/statistics.o ./src/statistics.c -I./include/\n",
    "!gcc -o ./bin/statdemo.exe  ./obj/statdemo.o ./obj/statistics.o"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You could compile **all of them** in a single command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o ./bin/statdemo ./src/statdemo.c  ./src/statistics.c -I./include/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mean is 4.400000\n"
     ]
    }
   ],
   "source": [
    "!.\\bin\\statdemo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Header Files \n",
    "\n",
    "`-I./include/`\n",
    "\n",
    "When compiling the program, the compiler needs the header files to compile the source codes;\n",
    "\n",
    "For each of the headers used in your source (via `#include directives`), \n",
    "\n",
    "Since the header's filename is known, the compiler only needs the `directories(path)`.\n",
    "\n",
    "The compiler searches the so-called **include-paths** for these headers. specified via `-Idir` option (or environment variable CPATH). \n",
    "\n",
    "* `-Idir`: The **include-paths** are specified (uppercase `I` followed by the directory path). \n",
    "\n",
    "\n",
    "\n",
    "List the **default** include-paths in your system used by the \"GNU C Preprocessor\" via `gcc -print-search-dirs`\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -print-search-dirs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.4 Makefile "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./makestatdemo.mk\n"
     ]
    }
   ],
   "source": [
    "%%file ./makestatdemo.mk\n",
    "\n",
    "all: statdemo\n",
    "\n",
    "statdemo: statobj  \n",
    "\tgcc -o ./bin/statdemo ./obj/statdemo.o ./obj/statistics.o \n",
    "\n",
    "statobj:  \n",
    "\tgcc -c -o ./obj/statdemo.o ./src/statdemo.c -I./include/ \n",
    "\tgcc -c -o ./obj/statistics.o  ./src/statistics.c -I./include/ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -c -o ./obj/statdemo.o ./src/statdemo.c -I./include/ \n",
      "gcc -c -o ./obj/statistics.o  ./src/statistics.c -I./include/ \n",
      "gcc -o ./bin/statdemo ./obj/statdemo.o ./obj/statistics.o \n"
     ]
    }
   ],
   "source": [
    "!make -f ./makestatdemo.mk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mean is 4.400000\n"
     ]
    }
   ],
   "source": [
    "!.\\bin\\statdemo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using the `variable` in  makefile\n",
    "\n",
    "A `variable` begins with a **`$`** and is enclosed within parentheses **(...)** \n",
    "\n",
    "* $(...)\n",
    "\n",
    "##### Makefile with variable\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing ./makestatdemo-var.mk\n"
     ]
    }
   ],
   "source": [
    "%%file ./makestatdemo-var.mk\n",
    "\n",
    "CC=gcc\n",
    "\n",
    "SRCDIR= ./src/\n",
    "OBJDIR= ./obj/\n",
    "BINDIR= ./bin/\n",
    "INCDIR=./include/\n",
    "\n",
    "all: statdemo\n",
    "\n",
    "statdemo: statobj  \n",
    "\t$(CC) -o $(BINDIR)statdemo $(OBJDIR)statdemo.o $(OBJDIR)statistics.o \n",
    "\n",
    "statobj:  \n",
    "\t$(CC) -c -o $(OBJDIR)statdemo.o $(SRCDIR)statdemo.c -I$(INCDIR) \n",
    "\t$(CC) -c -o $(OBJDIR)statistics.o  $(SRCDIR)statistics.c -I$(INCDIR) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -c -o ./obj/statdemo.o ./src/statdemo.c -I./include/ \n",
      "gcc -c -o ./obj/statistics.o  ./src/statistics.c -I./include/ \n",
      "gcc -o ./bin/statdemo ./obj/statdemo.o ./obj/statistics.o \n"
     ]
    }
   ],
   "source": [
    "!make -f makestatdemo-var.mk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mean is 4.400000\n"
     ]
    }
   ],
   "source": [
    "!.\\bin\\statdemo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4  The Advenced Makefile \n",
    "\n",
    "### 4.1 Automatic Variables\n",
    "\n",
    "**Automatic variables** are set by make after a rule is matched. \n",
    "\n",
    "There include:\n",
    "```bash\n",
    "$@: the target filename.\n",
    "$<: the first prerequisite filename.\n",
    "$^: All prerequisites with duplicates eliminated\n",
    "```\n",
    "### 4.2 Pattern Rules\n",
    "\n",
    "**A pattern rule**, which uses `pattern matching character` **`%`** as the `filename`, can be applied to create a target, if there is no explicit rule.\n",
    "\n",
    "```bash\n",
    "'%' matches filename.\n",
    "```\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.3  Functions "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4.3.1  Functions for File Names\n",
    "\n",
    "http://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html\n",
    "\n",
    "**$(notdir names…)**\n",
    "\n",
    "Extracts all `but the directory-part` of each file name in names. \n",
    "\n",
    " * remove the `path` of a file name\n",
    "\n",
    "For example, \n",
    "\n",
    "```\n",
    "$(notdir src/statistics.c src/statdemo.c)\n",
    "```\n",
    "produces the result  without `path`\n",
    "\n",
    "* `statistics.c statdemo.c`. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4.3.2 String Substitution and Analysis\n",
    "\n",
    "http://www.gnu.org/software/make/manual/html_node/Text-Functions.html\n",
    "\n",
    "\n",
    "**$(patsubst pattern, replacement, text)**\n",
    "\n",
    "Finds `whitespace-separated` words in text that match pattern and replaces them with replacement. \n",
    "\n",
    "* `text`(whitespace-separated words) -> **match** `pattern` -> **replaces** with `replacement`\n",
    "\n",
    "Here pattern may contain a **`%`**  which acts as a `wildcard`, matching any number of any characters within a word. \n",
    "\n",
    "For example, \n",
    "\n",
    "```\n",
    "$(patsubst %.c,  %.o, x.c y.c)\n",
    "```\n",
    "\n",
    "* pattern: %.c\n",
    "\n",
    "* replacement to: %.o\n",
    "\n",
    "* text: `x.c y.c` produces the value  `x.o y.o`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "### 4.5 Example The Advanced makefile for statistics\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./makestatdemo-adv.mk\n"
     ]
    }
   ],
   "source": [
    "%%file ./makestatdemo-adv.mk\n",
    "\n",
    "CC=gcc\n",
    "\n",
    "SRCDIR= ./src/\n",
    "OBJDIR= ./obj/\n",
    "BINDIR= ./bin/\n",
    "INCDIR= ./include/\n",
    "\n",
    "#SRCS=$(SRCDIR)statistics.c \\ \n",
    "#     $(SRCDIR)statdemo.c \n",
    "\n",
    "SRCS=$(wildcard $(SRCDIR)stat*.c)\n",
    "\n",
    "# non-path filename\n",
    "filename=$(notdir $(SRCS))\n",
    "\n",
    "# the obj target of a source code using the pattern rule\n",
    "OBJS=$(patsubst %.c,$(OBJDIR)%.o,$(filename))\n",
    "\n",
    "all:statdemo\n",
    "    \n",
    "statdemo: $(OBJS)  \n",
    "\t$(CC) -o $(BINDIR)$@ $^ \n",
    "\tdel .\\obj\\*.o\n",
    "\n",
    "$(OBJS):$(SRCS)\n",
    "\t$(CC) -o $@ -c $(SRCDIR)$(patsubst  %.o,%.c,$(notdir $@))  -I$(INCDIR) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcc -o obj/statistics.o -c ./src/statistics.c  -I./include/ \n",
      "gcc -o ./bin/statdemo obj/statistics.o obj/statdemo.o \n",
      "del .\\obj\\*.o\n"
     ]
    }
   ],
   "source": [
    "!make -f makestatdemo-adv.mk "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mean is 4.400000\n"
     ]
    }
   ],
   "source": [
    "!.\\bin\\statdemo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reference\n",
    "\n",
    "GCC (GNU compilers) http://gcc.gnu.org\n",
    "\n",
    "* [GCC Manual](http://gcc.gnu.org/onlinedocs)\n",
    "\n",
    "[GNU make Manual](http://www.gnu.org/software/make/manual/html_node/index.html)\n",
    "\n",
    "Robert Mecklenburg. [Managing Projects with GNU Make(Third Edition)](https://www.oreilly.com/openbook/make3/book/index.html)\n",
    "\n",
    "[GCC and Make：Compiling, Linking and Building C/C++ Applications](http://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html)\n",
    "\n",
    "[C/C++ Preprocessor Directives](http://www.cplusplus.com/doc/tutorial/preprocessor/)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.7"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "165px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
